package com.tyk.bookstore.back.logistics.controller;


import cn.dev33.satoken.annotation.SaCheckPermission;
import com.tyk.bookstore.back.common.core.excel.ExcelManager;
import com.tyk.bookstore.back.common.core.model.page.PageVo;
import com.tyk.bookstore.back.common.core.model.result.R;
import com.tyk.bookstore.back.logistics.manager.excel.constant.ExcelConstant;
import com.tyk.bookstore.back.logistics.manager.excel.model.WaybillExcelVo;
import com.tyk.bookstore.back.logistics.model.enume.WaybillState;
import com.tyk.bookstore.back.logistics.model.query.WaybillPageQuery;
import com.tyk.bookstore.back.logistics.model.query.WaybillUpdateQuery;
import com.tyk.bookstore.back.logistics.model.vo.WaybillPageVo;
import com.tyk.bookstore.back.logistics.model.vo.WaybillVo;
import com.tyk.bookstore.back.logistics.service.WaybillService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Set;

/**
 * @author tyk
 * @description 运单
 */
@RequestMapping({"api/logistics/waybill"})
@Tag(name = "物流管理/运单管理", description = "运单管理")
@RestController
@RequiredArgsConstructor
public class WaybillController {

    private final WaybillService waybillService;
    private final ExcelManager<WaybillExcelVo> excelManager;


    @Operation(summary = "查询运单详情", description = "查询运单详情")
    @SaCheckPermission("logistics:waybill:get")
    @GetMapping({"{id}"})
    public R<WaybillVo> getById(
            @Schema(description = "运单ID") @NotNull @Min(1)
            @PathVariable Long id
    ) {
        return R.ok(waybillService.getById(id));
    }


    @Operation(summary = "分页查询运单", description = "分页查询运单")
    @SaCheckPermission("logistics:waybill:page")
    @GetMapping({"page"})
    public R<WaybillPageVo> getPage(
            @Validated @ParameterObject WaybillPageQuery query,
            BindingResult br
    ) {
        return br.hasErrors() ? R.ok(PageVo.instance(WaybillPageVo.class)) : R.ok(waybillService.getPage(query));
    }

    @Operation(summary = "更新运单状态", description = "更新运单状态")
    @SaCheckPermission("logistics:waybill:update")
    @PutMapping
    public R<Object> updateById(
            @Validated @RequestBody WaybillUpdateQuery query
    ) {
        waybillService.updateById(query);
        return R.ok();
    }


    @Operation(summary = "接单", description = "下单->仓库接单->2发货")
    @SaCheckPermission("logistics:waybill:warehouse-receive")
    @GetMapping({"warehouse-receive/{id}"})
    public R<Object> warehouseReceived(
            @Schema(description = "运单ID") @NotNull @Min(1)
            @PathVariable Long id
    ) {
        waybillService.changeState(id, WaybillState.WAREHOUSE_RECEIVED);
        return R.ok();
    }


    @Operation(summary = "发货", description = "仓库接单->发货->揽件")
    @SaCheckPermission("logistics:waybill:deliver")
    @GetMapping({"deliver/{id}"})
    public R<Object> delivered(
            @Schema(description = "运单ID") @NotNull @Min(1)
            @PathVariable Long id) {
        waybillService.changeState(id, WaybillState.DELIVERED
        );
        return R.ok();
    }


    @Operation(summary = "揽件", description = "发货->揽件->运输")
    @SaCheckPermission("logistics:waybill:pick")
    @GetMapping({"pick/{id}"})
    public R<Object> pick(
            @Schema(description = "运单ID") @NotNull @Min(1)
            @PathVariable Long id
    ) {
        waybillService.changeState(id, WaybillState.PICKED);
        return R.ok();
    }


    @Operation(summary = "运输", description = "揽件->运输->派件")
    @SaCheckPermission("logistics:waybill:transport")
    @GetMapping({"transport/{id}"})
    public R<Object> transport(
            @Schema(description = "运单ID") @NotNull @Min(1)
            @PathVariable Long id
    ) {
        waybillService.changeState(id, WaybillState.TRANSPORTING);
        return R.ok();
    }


    @Operation(summary = "派件", description = "运输->派件->签收(会员行为)")
    @SaCheckPermission("logistics:waybill:dispatch")
    @GetMapping({"dispatch/{id}"})
    public R<Object> dispatch(
            @Schema(description = "运单ID") @NotNull @Min(1)
            @PathVariable Long id
    ) {
        waybillService.changeState(id, WaybillState.DISPATCHING);
        return R.ok();
    }


    @Operation(summary = "送达", description = "派件->送达(待签收)->签收(会员行为)")
    @SaCheckPermission("logistics:waybill:wait-pick")
    @GetMapping({"wait-pick/{id}"})
    public R<Object> waitPick(
            @Schema(description = "运单ID") @NotNull @Min(1)
            @PathVariable Long id
    ) {
        waybillService.changeState(id, WaybillState.WAIT_PICK);
        return R.ok();
    }


    @Operation(summary = "删除运单", description = "删除运单")
    @SaCheckPermission("logistics:waybill:delete")
    @DeleteMapping({"{id}"})
    public R<Object> deleteById(
            @Schema(description = "运单ID") @NotNull @Min(1)
            @PathVariable Long id
    ) {
        waybillService.deleteById(id);
        return R.ok();
    }


    @Operation(summary = "批量删除运单", description = "批量删除运单")
    @SaCheckPermission("logistics:waybill:delete")
    @DeleteMapping
    public R<Object> deleteBatchIdSet(
            @Schema(description = "运单ID列表") @NotNull @NotEmpty Set<Long> idList
    ) {
        waybillService.deleteBatchIdSet(idList);
        return R.ok();
    }

    @Operation(summary = "导出Excel", description = "导出Excel")
    @SaCheckPermission("logistics:waybill:excel:download")
    @GetMapping("excel")
    public void downloadExcel(WaybillPageQuery query, HttpServletResponse resp) {
        excelManager.write(
                waybillService.getWaybillExcelVoList(query),
                ExcelConstant.EXPRESS_COMPANY_FILE_NAME,
                ExcelConstant.EXPRESS_COMPANY_SHEET,
                resp
        );
    }

}
